home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_066 / dk / dk.mod < prev    next >
Text File  |  1992-05-06  |  12KB  |  402 lines

  1.  
  2.                                                                                                                                                                                                                                  (*$Q*)                              
  3. MODULE DK;
  4.  
  5. (* A little fun, inspired by Leo Schwab's TILT *)
  6.  
  7. (* Author: Thomas H. Handel, PeopleLink ID -- THH -- *)
  8.  
  9. (* I'm still learning Modula-2 and programming on Amy, so this may not
  10.    be the tidiest or best way to do what the program does.  Also, it is
  11.    probably not the most elegant example of structured programming ever
  12.    created.  Finally, I am certain that there are many enhancements that 
  13.    more experienced programmers will be able to add (like maybe a close 
  14.    gadget and the wherewithall to respond to it).  Please fiddle at will.     If you have comments or suggestions, please contact me on PeopleLink or    by U.S. Snail at:
  15.  
  16.    628 Harberts Ct.
  17.    Annapolis, MD 21401
  18.  
  19.    Thanks in advance. *)
  20.  
  21. (* Placed in the Public Domain, 29 March 1987 *)
  22.  
  23. FROM SYSTEM IMPORT ADR, BYTE, NULL;
  24. FROM Intuition IMPORT NewWindow, WindowPtr, IntuitionName, IntuitionBase,
  25.                       WindowFlags, WindowFlagSet, IDCMPFlagSet,
  26.                       ScreenFlagSet, WBenchScreen, SmartRefresh;
  27. FROM Libraries IMPORT OpenLibrary, CloseLibrary;
  28. FROM Windows IMPORT OpenWindow, CloseWindow;
  29. FROM Strings IMPORT String;
  30. FROM Pens IMPORT ReadPixel, WritePixel, SetAPen;
  31. FROM GraphicsLibrary IMPORT GraphicsName, GraphicsBase;
  32. FROM Rasters IMPORT RastPortPtr;
  33. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  34. FROM RandomNumbers IMPORT Random;
  35.  
  36. VAR WPtr: WindowPtr;
  37.     NWin: NewWindow;
  38.     WNam: String;
  39.     RprtPtr: RastPortPtr;
  40.  
  41.  
  42. PROCEDURE Initialize(): BOOLEAN;  (* Open the libraries *)
  43.  
  44. BEGIN
  45.    IntuitionBase := OpenLibrary(IntuitionName,0);
  46.    GraphicsBase := OpenLibrary(GraphicsName,0);
  47.    IF ((IntuitionBase = 0) OR (GraphicsBase = 0)) THEN RETURN FALSE
  48.       ELSE RETURN TRUE;
  49.    END;
  50. END Initialize;
  51.  
  52.  
  53. PROCEDURE InitWindow;  (* Set up and open the window *)
  54.  
  55. BEGIN
  56.    WNam := "DK!";
  57.    WITH NWin DO
  58.       LeftEdge := 450;
  59.       TopEdge := 0;
  60.       Width := 100;
  61.       Height := 10;
  62.       DetailPen := BYTE(0);
  63.       BlockPen := BYTE(1);
  64.       IDCMPFlags := IDCMPFlagSet{};
  65.       Flags := SmartRefresh + WindowFlagSet{Activate, WindowDepth};
  66.       FirstGadget := NULL;
  67.       CheckMark := NULL;
  68.       Title := ADR(WNam);
  69.       Screen := NULL;
  70.       BitMap := NULL;
  71.       MinWidth := 0;
  72.       MinHeight := 0;
  73.       MaxWidth := 0;
  74.       MaxHeight := 0;
  75.       Type := ScreenFlagSet{WBenchScreen};
  76.    END;
  77.    WPtr := OpenWindow(NWin);
  78. END InitWindow;
  79.  
  80.  
  81. PROCEDURE Decay; (* Erode the display *)
  82.  
  83.    TYPE ColNodePtr = POINTER TO ColNode;
  84.         ColNode = RECORD
  85.                     Col  : CARDINAL;  (* X-value of column *)
  86.                     Row  : CARDINAL;  (* Y-value of next non-zero pixel *)
  87.                     PClr : CARDINAL;  (* Pixel Pen number *)
  88.                     Next : ColNodePtr;  (* Forward pointer *)
  89.                     Prev : ColNodePtr  (* Backward pointer *)
  90.                   END;
  91.         PixlNodePtr = POINTER TO PixlNode;
  92.         PixlNode = RECORD
  93.                      PClr : CARDINAL; (* Pixel color *)
  94.                      CurX : CARDINAL; (* Current location, X-value *)
  95.                      CurY : CARDINAL; (* Current location, Y-value *)
  96.                      Next : PixlNodePtr; (* Forward pointer *)
  97.                      Prev : PixlNodePtr (* Backward pointer *)
  98.                    END;
  99.  
  100.    VAR ScrnTop   : CARDINAL;  (* Screen top *)
  101.        TopEdge   : CARDINAL;  (* Screen top less title bar *)
  102.        Bottom    : CARDINAL;  (* Screen bottom less border *)
  103.        YStrt     : CARDINAL;  (* Four pixels above bottom *)
  104.        ColCount  : CARDINAL;  (* Number of ColNodes in list *)
  105.        ColHead   : ColNodePtr; (* Pointer to head of ColNode list *)
  106.        CPtr      : ColNodePtr; (* Utility pointer for list traversal *)
  107.        PixlCount : CARDINAL;  (* Number of PixlNodes in list *)
  108.        PixlHead  : PixlNodePtr; (* Pointer to head of PixlNode list *)
  109.        PPtr      : PixlNodePtr; (* Utility pointer for list traversal *)
  110.        Depth     : ARRAY [2..637] OF CARDINAL; (* Depth of snow by col *)
  111.  
  112.  
  113.    PROCEDURE ComputeParms;  (* Get some basic parameters *)
  114.  
  115.    BEGIN
  116.       ScrnTop := WPtr^.WScreen^.TopEdge;
  117.       TopEdge := ScrnTop + 10;
  118.       Bottom := CARDINAL(WPtr^.WScreen^.Height) + ScrnTop - 1;
  119.       YStrt := Bottom - 4;
  120.    END ComputeParms;
  121.  
  122.  
  123.    PROCEDURE InitVars;  (* Initialize Variables *)
  124.  
  125.    VAR I : INTEGER; (* Counter *)
  126.  
  127.    BEGIN
  128.       FOR I := 2 TO 637 DO
  129.          Depth[I] := 0
  130.       END;
  131.       RprtPtr := ADR(WPtr^.WScreen^.RPort);
  132.       ColCount := 0;
  133.       PixlCount := 0;
  134.       ColHead := NIL;
  135.       PixlHead := NIL
  136.    END InitVars;
  137.  
  138.  
  139.    PROCEDURE FindCols;  (* Create list of cols containing non-zero pixls *)
  140.    VAR X    : CARDINAL; (* Column Counter *)
  141.        Y    : CARDINAL; (* Row Counter *)
  142.        Pixl : CARDINAL; (* Pen number of pixel *)
  143.  
  144.    BEGIN
  145.       FOR X := 2 TO 637 DO
  146.          Y := YStrt;
  147.          LOOP
  148.             Pixl := ReadPixel(RprtPtr,X,Y);
  149.             IF Pixl <> 0 THEN
  150.                NEW (CPtr);            (* Create node for list *)
  151.                CPtr^.Col := X;
  152.                CPtr^.Row := Y;
  153.                CPtr^.PClr := Pixl;
  154.                IF ColHead = NIL THEN  (* and link it in at head of list *)
  155.                   CPtr^.Next := NIL;
  156.                   CPtr^.Prev := NIL
  157.                ELSE
  158.                   CPtr^.Next := ColHead;
  159.                   CPtr^.Prev := NIL;
  160.                   ColHead^.Prev := CPtr
  161.                END;
  162.                ColHead := CPtr;
  163.                CPtr := NIL;
  164.                INC(ColCount);
  165.                EXIT
  166.             END;
  167.             Y := Y - 1;
  168.             IF Y <= TopEdge THEN
  169.                EXIT
  170.             END
  171.          END
  172.       END;
  173.    END FindCols;
  174.  
  175.  
  176.    PROCEDURE NewPixel;  (* Get a new pixel at random for snowflake ops *)
  177.  
  178.    VAR RNum : CARDINAL;  (* Random Number *)
  179.        I    : CARDINAL;  (* Counter *)
  180.        Pixl : CARDINAL;  (* Pen number of pixel *)
  181.  
  182.  
  183.       PROCEDURE DeleteCol;  (* Remove an empty column from the list *)
  184.  
  185.       BEGIN
  186.          IF CPtr = ColHead THEN
  187.             IF CPtr^.Next <> NIL THEN
  188.                ColHead := ColHead^.Next;
  189.                ColHead^.Prev := NIL
  190.             ELSE
  191.                ColHead := NIL
  192.             END
  193.          ELSE
  194.             IF CPtr^.Next = NIL THEN
  195.                CPtr^.Prev^.Next := NIL
  196.             ELSE
  197.                CPtr^.Prev^.Next := CPtr^.Next;
  198.                CPtr^.Next^.Prev := CPtr^.Prev
  199.             END
  200.          END;
  201.          DISPOSE (CPtr);
  202.          ColCount := ColCount - 1;
  203.       END DeleteCol;
  204.  
  205.  
  206.    BEGIN  (* NewPixel *)
  207.       RNum := Random(ColCount - 1);     (* 0 <= RNum <= [ColCount-1] *)
  208.       CPtr := ColHead;
  209.       IF RNum > 0 THEN
  210.          FOR I := 0 TO RNum DO
  211.             CPtr := CPtr^.Next
  212.          END
  213.       END;
  214.       NEW (PPtr);
  215.       PPtr^.PClr := CPtr^.PClr;
  216.       PPtr^.CurX := CPtr^.Col;
  217.       PPtr^.CurY := CPtr^.Row;
  218.       IF PixlHead = NIL THEN
  219.          PPtr^.Next := NIL;
  220.          PPtr^.Prev := NIL
  221.       ELSE
  222.          PPtr^.Next := PixlHead;
  223.          PPtr^.Prev := NIL;
  224.          PixlHead^.Prev := PPtr
  225.       END;
  226.       PixlHead := PPtr;
  227.       INC(PixlCount);
  228.       LOOP
  229.          CPtr^.Row := CPtr^.Row - 1;
  230.          IF CPtr^.Row < TopEdge THEN
  231.             DeleteCol;
  232.             EXIT
  233.          ELSE
  234.             Pixl := ReadPixel(RprtPtr,CPtr^.Col,CPtr^.Row);
  235.             IF Pixl <> 0 THEN
  236.                CPtr^.PClr := Pixl;
  237.                EXIT 
  238.             END
  239.          END
  240.       END;
  241.    END NewPixel;
  242.  
  243.  
  244.    PROCEDURE MovePixels;  (* Make the snow fall *)
  245.  
  246.    VAR XDest : CARDINAL;  (* Pixel destination, X-value *)
  247.        YDest : CARDINAL;  (* Pixel destination, Y-value *)
  248.        DFlag : BOOLEAN;  (* Signals pixel ready for deletion from list *)
  249.        RLFlag: BOOLEAN;  (* Direction of snow drift *)
  250.  
  251.  
  252.       PROCEDURE DeletePixel;  (* Remove a pixel from the list *)
  253.  
  254.       VAR tPtr : PixlNodePtr;  (* Utility pointer *)
  255.  
  256.       BEGIN
  257.          tPtr := PPtr;
  258.          IF PPtr = PixlHead THEN
  259.             IF PPtr^.Next <> NIL THEN
  260.                PixlHead := PixlHead^.Next;
  261.                PixlHead^.Prev := NIL
  262.             ELSE
  263.                PixlHead := NIL
  264.             END;
  265.             tPtr := PPtr;
  266.             PPtr := PixlHead
  267.          ELSE
  268.             IF PPtr^.Next = NIL THEN
  269.                PPtr^.Prev^.Next := NIL
  270.             ELSE
  271.                PPtr^.Prev^.Next := PPtr^.Next;
  272.                PPtr^.Next^.Prev := PPtr^.Prev
  273.             END;
  274.             tPtr := PPtr;
  275.             PPtr := PPtr^.Prev
  276.          END;
  277.          DISPOSE (tPtr);
  278.          PixlCount := PixlCount - 1;
  279.          DFlag := FALSE;
  280.       END DeletePixel;
  281.  
  282.  
  283.       PROCEDURE ComputeDest;  (* Compute a random destination for pixel *)
  284.  
  285.       BEGIN
  286.          XDest := PPtr^.CurX + 8 - Random(16);
  287.          YDest := PPtr^.CurY + Random(13);
  288.          IF XDest <= 2 THEN
  289.             XDest := 3 + Random(5)
  290.          END;
  291.          IF XDest >= 637 THEN
  292.             XDest := 636 - Random(5)
  293.          END;
  294.          IF YDest > Bottom - Depth[XDest] THEN
  295.             YDest := Bottom - Depth[XDest];
  296.             DFlag := TRUE
  297.          END;
  298.       END ComputeDest;
  299.  
  300.  
  301.       PROCEDURE Drift;  (* Keep the snow from stacking up in tall towers *)
  302.       VAR ChgFlag : BOOLEAN;  (* Flags change in XDest *)
  303.  
  304.  
  305.          PROCEDURE CheckLeft;  (* See if flake should drift left *)
  306.  
  307.          BEGIN
  308.             IF Depth[XDest] > Depth[XDest-1] THEN
  309.                XDest := XDest - 1;
  310.                ChgFlag := TRUE
  311.             END
  312.          END CheckLeft;
  313.  
  314.  
  315.          PROCEDURE CheckRight;  (* See if flake should drift right *)
  316.  
  317.          BEGIN
  318.             IF Depth[XDest] > Depth[XDest+1] THEN
  319.                INC(XDest);
  320.                ChgFlag := TRUE
  321.             END
  322.          END CheckRight;
  323.  
  324.       BEGIN (* Drift *)
  325.          ChgFlag := TRUE;
  326.          WHILE (XDest > 2) AND (XDest < 637) AND (ChgFlag) DO
  327.             ChgFlag := FALSE;
  328.             IF RLFlag THEN
  329.                CheckLeft;
  330.                CheckRight
  331.             ELSE
  332.                CheckRight;
  333.                CheckLeft
  334.             END;
  335.             YDest := Bottom - Depth[XDest] - 1
  336.          END
  337.       END Drift;
  338.  
  339.  
  340.       PROCEDURE MoveOne;  (* Move one pixel to new destination *)
  341.  
  342.       BEGIN
  343.          SetAPen(RprtPtr,0);
  344.          WritePixel(RprtPtr,PPtr^.CurX,PPtr^.CurY);
  345.          SetAPen(RprtPtr,PPtr^.PClr);
  346.          WritePixel(RprtPtr,XDest,YDest);
  347.          PPtr^.CurX := XDest;
  348.          PPtr^.CurY := YDest;
  349.       END MoveOne;
  350.  
  351.    BEGIN (* MovePixels *)
  352.       RLFlag := TRUE;
  353.       DFlag := FALSE;
  354.       PPtr := PixlHead;
  355.       WHILE PPtr <> NIL DO           (* While there are still flakes *)
  356.          ComputeDest;                (* Find this one a new destination *)
  357.          IF DFlag THEN               (* If it has landed *)
  358.             Drift;                   (* See if it should roll R or L *)
  359.             RLFlag := NOT(RLFlag)
  360.          END;
  361.          MoveOne;                    (* Actually move it to new dest *)
  362.          IF DFlag THEN               (* If it has landed *)
  363.             INC(Depth[XDest]);       (* increment depth in column *)
  364.             DeletePixel              (* and remove pixel from list *)
  365.          END;
  366.          IF PPtr <> NIL THEN
  367.             PPtr := PPtr^.Next
  368.          END
  369.       END
  370.    END MovePixels;
  371.  
  372. BEGIN (* Decay *)
  373.    ComputeParms;
  374.    InitVars;
  375.    FindCols;
  376.    REPEAT
  377.       IF ColCount <> 0 THEN  
  378.          NewPixel
  379.       END;
  380.       IF PixlCount <> 0 THEN
  381.          MovePixels
  382.       END
  383.    UNTIL (ColCount = 0) AND (PixlCount = 0);
  384. END Decay;
  385.  
  386.  
  387. PROCEDURE DanceOff;  (* Clean things up *)
  388.  
  389. BEGIN
  390.    CloseWindow(WPtr);
  391.    CloseLibrary(IntuitionBase);
  392.    CloseLibrary(GraphicsBase);
  393. END DanceOff;
  394.  
  395. BEGIN (* DK *)
  396.    IF Initialize() THEN
  397.      InitWindow;
  398.      Decay;
  399.      DanceOff;
  400.    END;
  401. END DK.
  402.